// sm2_verify.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "utils.h"

int main(int argc, char *argv[]) {
    if (argc < 5 || argc > 6) {
        fprintf(stderr, "Usage: %s <input_file> <pubkey.pem> <sig_file> <id> [expected_sig_file]\n", argv[0]);
        exit(1);
    }

    const char *in_file = argv[1];
    const char *pubkey_file = argv[2];
    const char *sig_file = argv[3];
    const char *id = argv[4];

    size_t in_len, sig_len;
    unsigned char *in_data = read_file(in_file, &in_len);
    unsigned char *sig = read_file(sig_file, &sig_len);

    FILE *fp = fopen(pubkey_file, "r");
    EVP_PKEY *pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
    fclose(fp);
    if (!pkey) {
        fprintf(stderr, "Failed to read public key\n");
        exit(1);
    }

    EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
    if (!md_ctx) goto err;

    int ret = (EVP_DigestVerifyInit(md_ctx, NULL, EVP_sm3(), NULL, pkey) > 0 &&
               EVP_PKEY_CTX_set_ec_scheme(EVP_MD_CTX_pkey_ctx(md_ctx), NID_sm2) > 0 &&
               EVP_PKEY_CTX_set1_id(EVP_MD_CTX_pkey_ctx(md_ctx), id, strlen(id)) > 0 &&
               EVP_DigestVerify(md_ctx, sig, sig_len, in_data, in_len) > 0);

    EVP_MD_CTX_free(md_ctx);
    EVP_PKEY_free(pkey);
    free(in_data);
    free(sig);

    if (ret) {
        printf("Verify: success\n");
        return 0;
    } else {
        printf("Verify: failed\n");
        exit(1);
    }

err:
    fprintf(stderr, "SM2 verification failed.\n");
    EVP_MD_CTX_free(md_ctx);
    EVP_PKEY_free(pkey);
    free(in_data);
    free(sig);
    exit(1);
}
